#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author: twl
@date: 2022/5/9 11:03
@description:
"""
import io
import time
import base64
import pandas as pd

from .utils import show, steady
from base.entity.base_entity import db
from datetime import datetime, timedelta
from tsmoothie import ConvolutionSmoother
from flask import jsonify, request, Blueprint


wakeupTime = Blueprint('wakeUpTime', __name__)


@wakeupTime.route('/res', methods=['GET'])
def wakeup_time():
    # activeId = "86105349"
    # morningStartTime = " 02:00:00"
    # morningEndTime = " 10:00:00"
    # # 牙刷
    # sc_mac = '50:3D:C6:C5:9E:73'
    # day = '220519'

    register_dict = request.args
    activeId = register_dict['activeId']
    morningStartTime = " " + register_dict['morningStartTime']
    morningEndTime = " " + register_dict['morningEndTime']
    sc_mac = register_dict['sc_mac']
    day = register_dict['day']
    format =  request.args.get('format', '')
    if format!="img":
        format = "json"
    data = (0, [])
    try:
        date = "20" + day[0:2] + "-" + day[2:4] + "-" + day[4:6]
        # current_app.logger.info("----------------------------")

        startTime = date + morningStartTime
        moendTime = date + morningEndTime

        diff = datetime.strptime(moendTime, "%Y-%m-%d %H:%M:%S") - datetime.strptime(startTime, "%Y-%m-%d %H:%M:%S")
        st = datetime.strptime(startTime, "%Y-%m-%d %H:%M:%S")
        et = datetime.strptime(moendTime, "%Y-%m-%d %H:%M:%S")

        stamp = int(time.mktime(st.timetuple()) * 1000.0 + st.microsecond / 1000.0)
        etamp = int(time.mktime(et.timetuple()) * 1000.0 + et.microsecond / 1000.0)

        timeSeqKeys = []
        intervalRange = round(diff.seconds / 60 / 1)

        sql = """
        SELECT
          FROM_UNIXTIME(log_time/1000,'%%H:%%i') AS d,
          distance AS v,
          log_time
        FROM
          sc_bluetooth_device_%s
         WHERE mac='%s' AND  log_time>='%s' AND log_time<='%s' AND active_id='%s'  ORDER BY log_time ASC """ % (
        day, sc_mac, stamp, etamp, activeId)

        data = db.session.execute(sql).fetchall()
    except:
        return jsonify({"wakeUpTimes": [],"code":-1})

    if len(data) == 0:
        return jsonify({"wakeUpTimes": [],"code":-2})

    if len(data)<(intervalRange*0.5)-100:
        return jsonify({"wakeUpTimes": [], "code": -3})

    rowsTimeSeqV = {}
    if len(data) > 0:
        for rows in data:
            rowsTimeSeqV[rows[0]] = rows[1]
    dt1 = pd.date_range(startTime, periods=intervalRange, freq='1min')
    res = {}
    for i, t in enumerate(dt1):
        key = str(t)[11:16]
        if key in rowsTimeSeqV:
            res[key] = rowsTimeSeqV[key]
        else:
            res[key] = None
            # 减少离群值影响，2，删除，找干扰因素，根据现实情况
            # print("%s key no value，is %s " % (key, res[key]))

    ############ parameter
    window_sizes = 30

    point = list(res.keys())
    if len(point) > 0:
        distance1 = list(res.values())
        keys = list(res.keys())

        ## 生成数据
        df = pd.DataFrame(
            {
                'BluetoothDistance': distance1
            },
            index=keys
        )

        # a, interpolation
        df = df.interpolate(method='linear', limit_direction='forward')

        # a, smoothing
        steady_df = steady(list(df["BluetoothDistance"]))
        smoother = ConvolutionSmoother(window_len=30, window_type='ones')
        bts_samples = smoother.smooth([steady_df])
        smooth_data = smoother.smooth_data[0]
        smooth_data = pd.Series(smooth_data)

        # b, difference
        diff = smooth_data.diff(periods=1).rolling(window=window_sizes)

        # c, window's variance
        # sum
        rwsum = diff.sum(ddof=1)
        min_sum = rwsum.min() / 3
        # var
        rwvar = diff.std(ddof=1)

        flag = None
        n = len(rwsum)
        assert n > 200, ValueError(f"Data that it's length is '{n}' is too small ")

        """ 循环过滤 """
        a, b = 2, 1.3
        iteration = 0
        while not flag and iteration < 6:
            best_sum, best_var = 0, 0
            for i, (s, v) in enumerate(zip(rwsum, rwvar)):
                if i >= n - window_sizes:
                    break
                if i >= window_sizes:
                    post_sum, post_var = rwsum[i + window_sizes // 2], rwvar[i + window_sizes // 2]

                    # var 大的时候， sum可能趋向0，通过abs解决；
                    # 判断条件： sum和var 两部分 存在差值时，中间有一大段边缘， 通过记录前一时间的pre值判断是否变化
                    # if s < post_sum/a and abs(v) < abs(post_var)/b:
                    if abs(v) < abs(post_var) / b:  # 方差大
                        if abs(s) < abs(post_sum) / a:  # 保证 波动值 大，或者 趋于了零
                            if best_sum < (abs(post_sum) - abs(s)) and best_var < (abs(post_var) - abs(v)):
                                # 排除离家情况 : 取 最大负值sum的一半进行比较即可
                                if post_sum > min_sum:
                                    best_var = (abs(post_var) - abs(v))
                                    best_sum = (abs(post_sum) - abs(s))
                                    flag = i
                else:
                    pass
            a -= 0.1
            iteration += 1
        if flag is None:
            vline = flag
            analysisRes = [0]
            print('***************          None        ')
        else:
            vline = flag
            analysisRes = [list(df.index)[vline]]   # .replace(":", "：")

        if format == 'img':
            s = io.BytesIO()
            """ plotting  """
            show(df, date, sc_mac, activeId, smooth_data, (vline, analysisRes[0]), ifsave=s)  # True
            s = base64.b64encode(s.getvalue()).decode("utf-8").replace("\n", "")
            return '<p style="text-align:center;"><img src="data:image/png;base64,%s"></p>' % s
        else:
            return jsonify({"wakeUpTimes—candidates": analysisRes, "hits": analysisRes[0], "code": 0})
